//Buffer缓冲区模块
#pragma once
#include<vector>
#include<iostream>
#include<cassert>
#include<algorithm>
#include<cstring>

#define DEFAULT_BUFFER_SIZE 1024
class Buffer{
private:
    std::vector<char> _buf;//存储数据的容器
    uint64_t read_pos;//读位置 
    uint64_t write_pos;//写位置
public:
    Buffer()
    :_buf(DEFAULT_BUFFER_SIZE),
    read_pos(0),
    write_pos(0)
    {}

    //获取读位置指针
    char* get_read_ptr()
    {
        return (&*_buf.begin()) + read_pos;
    }

    //获取可读空间大小
    uint64_t get_readable_size()
    {
        return write_pos-read_pos;
    }

    //移动读指针
    void move_read_pos(uint64_t len)
    {
        read_pos += len;
    }

    //只读数据不删除
    void only_read(char* buf, uint64_t len)
    {
        //确保读安全
        assert(get_readable_size() >= len);

        std::copy(get_read_ptr(), get_read_ptr()+len, buf);
    }
    //读数据并弹出
    void read(char* buf, uint64_t len)
    {
        only_read(buf, len);
        read_pos += len;
    }

    //以string的形式读,不删除
    std::string  string_only_read(uint64_t len)
    {
        assert(get_readable_size() >= len);
        std::string str(len, 0);
        std::copy(get_read_ptr(), get_read_ptr()+len, str.begin());
        return str;
    }
    //sting读
    std::string string_read(uint64_t len)
    {
        std::string str = string_only_read(len);
        read_pos += len;
        return str;
    }

    //以Buffer的形式读，不删除
    Buffer Buffer_only_read(uint64_t len)
    {
        assert(get_readable_size() >= len);
        Buffer b;
        char buf[len];
        this->read(buf, len);
        b.write(buf, len);
        return b;
    }
    //以Buffer的形式读并删除
    Buffer Buffer_read(uint64_t len)
    {
        Buffer ret = Buffer_only_read(len);
        read_pos += len;
        return ret;
    }

    //按行读，遇到\n。读但不删除
    std::string line_read()
    {
        char* ptr = (char*)memchr(get_read_ptr(), '\n',get_readable_size());
        if(ptr == nullptr)
        {
            return "";
        }
        std::string ret = this->string_read(ptr-get_read_ptr()+1);//把'\n'也取出来
        read_pos += ptr-get_read_ptr()+1;
        return ret;
    }

    //获取写位置的指针
    char* get_write_ptr()
    {
        return (&*_buf.begin()) + write_pos;
    }

    //获取写位置后面的写空间大小
    uint64_t get_tail_wsize()
    {
        return _buf.size()-write_pos;
    }

    //获取读位置前面的写空间大小
    uint64_t get_head_wsize()
    {
        return  read_pos;
    }

    //确保写空间足够
    void wspace_manager(uint64_t len)
    {
        if(len <= get_tail_wsize())
        {
            //如果后沿空间足够，直接返回
            return;
        }
        else if(len <= get_tail_wsize()+get_head_wsize())
        {
            //如果后沿空间不够，但是剩余写空间足够，移动数据
            std::copy(_buf.begin()+read_pos, _buf.begin()+write_pos, _buf.begin());
            read_pos = 0;
            write_pos = get_readable_size();
        }
        else
        {
            //如果剩余空间不够，就扩容
            _buf.resize(write_pos+len);
        }
    }

    //只写数据不推入
    void only_write(const char* buf, uint64_t len)
    {
        wspace_manager(len);
        std::copy(buf, buf+len, get_write_ptr());
    }
    //写数据并推入
    void write(const char* buf, uint64_t len)
    {
        only_write(buf, len);
        write_pos += len;
    }

    //以string方式写，不推入
    void string_only_write(std::string str, uint64_t len)
    {
        wspace_manager(len);
        std::copy(str.begin(), str.end(), get_write_ptr());
    }
    //以string方式写并推入
    void string_write(std::string str, uint64_t len)
    {
        string_only_write(str, len);
        write_pos += len;
    }

    //以Buffer的形式写，不推入
    void Buffer_only_write(Buffer b)
    {
        only_write(b.get_read_ptr(), b.get_readable_size());
    }
    //以Buffer的形式写并推入
    void Buffer_write(Buffer b)
    {
        write(b.get_read_ptr(), b.get_readable_size());
    }
    
    //清空数据
    void clear()
    {
        read_pos = 0;
        write_pos = 0;
    }
};
